package org.korecky.gnotedigitalorganizer.svg;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.korecky.gnotedigitalorganizer.data.SvgPoint;

/**
 * 
 * @author vkorecky
 */
public class DntToSvg {
    // private double SIZING = 0.0254;
    private final double ORIGIN_X = 0.50260097;
    private final double ORIGIN_Y = 0.50263572;
    private final double XSIZING = 0.045957671957672;
    private final double YSIZING = 0.0463621399176955;
    private final float YSIZE = 22677;
    private final float XSIZE = 16169;

    // private double WIDTH_CM = 30.0;

    public static enum penEnum {
	UP(0xE0), BLACK(0xA1), RED(0xA5);

	// code
	private final int code;

	penEnum(int code) {
	    this.code = code;
	}

	/**
	 * Get commandID
	 * 
	 * @return
	 */
	public int getCode() {
	    return code;
	}
    }

    private SvgPoint rotate(SvgPoint originalPoint) {
	SvgPoint rotatedPoint = new SvgPoint();
	rotatedPoint.setX(XSIZE - originalPoint.getY());
	rotatedPoint.setY(originalPoint.getX());
	return rotatedPoint;
    }

    /**
     * Converts DNT to SVG
     * 
     * @param dntFilePath
     * @return
     * @throws IOException
     */
    public String Convert(String dntFilePath) throws IOException {
	FileInputStream dntFileStream = new FileInputStream(dntFilePath);
	return Convert(dntFileStream);
    }

    /**
     * Converts DNT to SVG
     * 
     * @param dntFileStream
     * @return
     * @throws IOException
     */
    public String Convert(InputStream dntFileStream) throws IOException {
	StringBuilder stringBuilder = new StringBuilder();

	try {
	    // Read hedar (64 bytes)
	    byte[] headerByteArray = new byte[64];
	    dntFileStream.read(headerByteArray, 0, 64);

	    // Write SVG header
	    stringBuilder.append("<?xml version=\"1.0\" standalone=\"no\"?>");
	    stringBuilder.append("\n");
	    stringBuilder.append("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">");
	    stringBuilder.append("\n");
	    // pw.println("<svg width=\"" + String.valueOf(WIDTH_CM) +
	    // "cm\" height=\"" + String.valueOf(WIDTH_CM / XSIZE * YSIZE) +
	    // "cm\" viewBox=\"0 0 " + String.valueOf((XSIZE - 1) * SIZING) +
	    // " " + String.valueOf((YSIZE - 1) * SIZING) +
	    // "\" version=\"1.1\"");
	    // width=\"21cm\" height=\"29.7cm\"
	    stringBuilder.append("<svg width=\"210mm\" height=\"297mm\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.2\">");
	    stringBuilder.append("\n");
	    // Show outline of canvas using 'rect' element
	    stringBuilder.append("  <rect x=\"0\" y=\"0\" width=\"" + String.valueOf(XSIZE * XSIZING) + "\" height=\"" + String.valueOf(YSIZE * YSIZING) + "\" fill=\"none\" stroke=\"black\" stroke-width=\"1\"/>");
	    stringBuilder.append("\n");

	    // read the content
	    byte[] recordByteArray = new byte[8];
	    penEnum penStatus = penEnum.UP;
	    while (dntFileStream.read(recordByteArray, 0, 8) != -1) {
		// COnvert first byte to unsigned byte
		int tempByte = (0x000000FF & ((int) recordByteArray[0]));
		short anUnsignedByte = (short) tempByte;

		if ((anUnsignedByte == 0xe0) && (penStatus != penEnum.UP)) {
		    // end of the path
		    if (penStatus == penEnum.BLACK) {
			stringBuilder.append("\" style=\"fill:none;stroke:black;stroke-width:1\"/>");
			stringBuilder.append("\n");
		    }
		    else if (penStatus == penEnum.RED) {
			stringBuilder.append("\" style=\"fill:none;stroke:red;stroke-width:1\"/>");
			stringBuilder.append("\n");
		    }
		    penStatus = penEnum.UP;
		}
		else {
		    // the "magic" conversion
		    float x = recordByteArray[1] + recordByteArray[2] * 128 + (recordByteArray[6] & 0x01) * 128 * 128;
		    float y = recordByteArray[3] + recordByteArray[4] * 128 + ((recordByteArray[6] & 0x04) >> 2) * 128 * 128;
		    SvgPoint rotatedPoint = rotate(new SvgPoint(x, y));

		    // output the path
		    if (penStatus == penEnum.UP) {
			stringBuilder.append("   <path d=\"M" + String.valueOf(ORIGIN_X + (rotatedPoint.getX() * XSIZING)) + " " + String.valueOf(ORIGIN_Y + (rotatedPoint.getY() * YSIZING)) + " ");
			stringBuilder.append("\n");
			if (anUnsignedByte == 0xA1)
			    penStatus = penEnum.BLACK;
			else if (anUnsignedByte == 0xA5)
			    penStatus = penEnum.RED;
		    }
		    else {
			stringBuilder.append("L" + String.valueOf(ORIGIN_X + (rotatedPoint.getX() * XSIZING)) + " " + String.valueOf(ORIGIN_Y + (rotatedPoint.getY() * YSIZING)) + " ");
			stringBuilder.append("\n");
		    }
		}
	    }
	    stringBuilder.append("</svg>");
	    stringBuilder.append("\n");
	}
	finally {
	    dntFileStream.close();
	}
	return stringBuilder.toString();
    }
}
